/// @file
/// @author Chelsey Batchelor <vadedeyes@gmail.com>
/// @author Abraham Escamilla <abraham.escamilla@live.com>
/// @author Curtis Hollibaugh <curtis.hollibaugh@gmail.com>
/// @copyright Copyright 2014 Chelsey Batchelor <vadedeyes@gmail.com>
/// @copyright Copyright 2014 Abraham Escamilla <abraham.escamilla@live.com>
/// @copyright Copyright 2014 Curtis Hollibaugh <curtis.hollibaugh@gmail.com>
/// Contains tests written while learning the GTK+ framework.

#include <chrono>
#include <gtest/gtest.h>
#include <gtk/gtk.h>
#include <mutex>
#include <thread>

using std::bind;
using std::chrono::milliseconds;
using std::lock_guard;
using std::mutex;
using std::thread;

/// Creates a 100x100 window, shows it, and hides it.
TEST(LearnGTK, BasicExample) {
	gtk_init(0, nullptr);
	
	mutex gtkLock{};
	bool quitting{false};
	
	thread tests{
		[&gtkLock, &quitting] () {
			gtkLock.lock();
			
			auto window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			gtk_window_set_default_size(GTK_WINDOW(window), 100, 100);
			gtk_widget_show(window);
			
			gtkLock.unlock();
			
			//std::this_thread::sleep_for(milliseconds{1000}); // uncomment this line to see the tray icon
			
			gtkLock.lock();
			
			gtk_widget_hide(window);
			gtk_widget_destroy(window);
			window = nullptr;
			
			quitting = true;
			
			gtkLock.unlock();
		}
	};
	
	while(true) {
		gtkLock.lock();
		if(quitting) break;
		gtk_main_iteration_do(false);
		gtkLock.unlock();
	}
	
	tests.join();
}

/// Creates a window with button, shows it, and hides it.
TEST(LearnGTK, ButtonHelloWorld) {
	gtk_init(0, nullptr);
	
	mutex gtkLock{};
	bool quitting{false};
	
	thread tests{
		[&gtkLock, &quitting] () {
			gtkLock.lock();
			
			auto window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
			g_signal_connect(window, "destroy", G_CALLBACK([](){}), nullptr);
			gtk_container_set_border_width(GTK_CONTAINER(window), 10);
			
			auto button = gtk_button_new_with_label("Hello World");
			gtk_container_add(GTK_CONTAINER(window), button);
			
			gtk_widget_show_all(window);
			
			gtkLock.unlock();
			
			//std::this_thread::sleep_for(milliseconds{10000}); // uncomment this line to see the tray icon
			
			gtkLock.lock();
			
			gtk_widget_hide(window);
			
			window = nullptr;
			
			quitting = true;
			
			gtkLock.unlock();
		}
	};
	
	while(true) {
		gtkLock.lock();
		if(quitting) break;
		gtk_main_iteration_do(false);
		gtkLock.unlock();
	}
	
	tests.join();
}

/// Creates a tray icon, shows it, and hides it.
TEST(LearnGTK, TrayIcon) {
	gtk_init(0, nullptr);
	
	mutex gtkLock{};
	bool quitting{false};
	
	thread tests{
		[&gtkLock, &quitting] () {
			gtkLock.lock();
			
			auto ti = gtk_status_icon_new_from_file("res/icon.png");
			EXPECT_EQ(true, gtk_status_icon_get_visible(ti));
			
			gtk_status_icon_set_visible(ti, true);
			EXPECT_EQ(true, gtk_status_icon_get_visible(ti));
			
			gtkLock.unlock();
			
			//std::this_thread::sleep_for(milliseconds{1000}); // uncomment this line to see the tray icon
			
			gtkLock.lock();
			
			gtk_status_icon_set_visible(ti, false);
			EXPECT_EQ(false, gtk_status_icon_get_visible(ti));
			quitting = true;
			
			g_object_unref(G_OBJECT(ti));
			
			gtkLock.unlock();
		}
	};
	
	while(true) {
		gtkLock.lock();
		if(quitting) break;
		gtk_main_iteration_do(false);
		gtkLock.unlock();
	}
	
	tests.join();
}
